package com.zzy.template.controller;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zzy.template.common.ZZYResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BaseController<T> {

    @Autowired
    private IService<T> service;

    //add List
    @PostMapping("/add")
    public ZZYResult add(@RequestBody List<T> t) {
        boolean b = service.saveBatch(t);
        return new ZZYResult(200, "添加操作", b);
    }

    //del List
    @DeleteMapping("/del")
    public ZZYResult del(@RequestBody List<Long> ids) {
        boolean b = service.removeByIds(ids);
        return new ZZYResult(200, "删除操作", b);
    }

    //update List
    @PutMapping("/change")
    public ZZYResult change(@RequestBody List<T> t) {
        boolean b = service.updateBatchById(t);
        return new ZZYResult(200, "修改操作", b);
    }

    //get one
    @GetMapping("/get/{id}")
    public ZZYResult getOne(@PathVariable Long id) {
        T one = service.getById(id);
        return new ZZYResult(200, "查询操作", one);
    }

    //query List condition
    /**
     * {
     *     condition:{
     *         eq:[{key:key,value:value,isAnd:true}],
     *         gt:[{key:key,value:value}],
     *         lt:[{key:key,value:value}],
     *         between:[{
     *                 "column":"id",
     *                 "start":1,
     *                 "end":10,
     *                 isAnd:true
     *             }],
     *         scope:[{column:a,value:[1,2,3],isIn:true,isAnd:true}],
     *         order:[{column:[1,2,3],isAsc:true}]
     *         group:[1,2,3]
     *     },
     *     page:{
     *         current:1,
     *         size:10
     *     }
     * }
     * @param jsonObject
     * @return
     */
    @PostMapping("/page")
    public ZZYResult page(@RequestBody JSONObject jsonObject) {
        if (jsonObject == null){
            return new ZZYResult(200,"无数据",null);
        }
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        QueryWrapper<T> condition = resolverCondition(wrapper, jsonObject);
        Page<T> tPage = resolverPage(jsonObject);
        Page<T> page = service.page(tPage,condition);
        long total = page.getTotal();
        long pages = page.getPages();
        List<T> records = page.getRecords();
        Map map = new HashMap();
        map.put("total",total);
        map.put("pages",pages);
        map.put("data",records);
        return new ZZYResult(200,"分页查询",map);
    }

    @PostMapping("/queryList")
    public ZZYResult queryList(@RequestBody JSONObject jsonObject) {
        if (jsonObject == null || jsonObject.size() == 0){
            List<T> list = service.list();
            return new ZZYResult(200,"无数据",list);
        }
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        QueryWrapper<T> condition = resolverCondition(wrapper, jsonObject);

        List<T> list = service.list(condition);
        return new ZZYResult(200,"列表查询",list);
    }

    public QueryWrapper<T> resolverCondition(QueryWrapper<T> wrapper, JSONObject jsonObject) {
        JSONObject condition = jsonObject;
        if (condition == null) {
            return wrapper;
        }

        JSONArray eq = condition.getJSONArray("eq");
        if (eq != null) {
            for (Object o : eq) {
                cn.hutool.json.JSONObject obj = JSONUtil.parseObj(o);
                String key = obj.getStr("key");
                String value = obj.getStr("value");
                Boolean isAnd = obj.getBool("isAnd");
                if (key == null || value == null){
                    continue;
                }
                wrapper.eq(key, value);
                if (isAnd != null && !isAnd){
                    wrapper.or();
                }
            }
        }

        JSONArray gt = condition.getJSONArray("gt");
        if (gt != null) {
            for (Object o : gt) {
                JSONObject obj = (JSONObject) o;
                String key = obj.getString("key");
                Integer value = obj.getInteger("value");
                if (key == null || value == null){
                    continue;
                }
                wrapper.gt(key, value);
            }
        }

        JSONArray lt = condition.getJSONArray("lt");
        if (lt != null) {
            for (Object o : lt) {
                cn.hutool.json.JSONObject obj = JSONUtil.parseObj(o);
                String key = obj.getStr("key");
                Integer value = obj.getInt("value");
                if (key == null || value == null){
                    continue;
                }
                wrapper.lt(key, value);
            }
        }

        JSONArray scope = condition.getJSONArray("scope");
        if (scope != null && scope.size() != 0) {
            for (Object o : scope) {
                cn.hutool.json.JSONObject obj = JSONUtil.parseObj(o);
                String column = obj.getStr("column");
                cn.hutool.json.JSONArray value = obj.getJSONArray("value");
                Boolean isIn = obj.getBool("isIn");
                Boolean isAnd = obj.getBool("isAnd");
                if ("".equals(column) || column == null || value == null || value.size() == 0){
                    continue;
                }
                if (isIn == null || isIn ){
                    wrapper.in(column,value);
                }else {
                    wrapper.notIn(column,value);
                }
                if (isAnd != null && !isAnd){
                    wrapper.or();
                }
            }
        }

        JSONArray between = condition.getJSONArray("between");
        if (between != null && between.size() != 0) {
            for (Object o : between) {
                cn.hutool.json.JSONObject obj = JSONUtil.parseObj(o);
                String column = obj.getStr("column");
                Long start = obj.getLong("start");
                Long end = obj.getLong("end");
                Boolean isAnd = obj.getBool("isAnd");
                if (start == null || column == null || end == null){
                    continue;
                }
                wrapper.between(column,start,end);
                if (isAnd != null && !isAnd){
                    wrapper.or();
                }
            }
        }

        JSONArray group = condition.getJSONArray("group");
        if (group != null && group.size() != 0) {
            List<String> str = group.toJavaList(String.class);
            String [] a = new String[]{};
            String[] strings = str.toArray(a);
            wrapper.groupBy(strings).select(strings);
        }

        JSONArray order = condition.getJSONArray("order");
        if (order != null && order.size() != 0){
            for (Object o : order) {
                cn.hutool.json.JSONObject obj = JSONUtil.parseObj(o);
                cn.hutool.json.JSONArray column = obj.getJSONArray("column");
                Boolean isAsc = obj.getBool("isAsc");
                String [] columns = new String[]{};
                if (isAsc == null || isAsc){
                    wrapper.orderByAsc(column.toArray(columns));
                }else {
                    wrapper.orderByDesc(column.toArray(columns));
                }
            }
        }

        return wrapper;
    }

    public Page<T> resolverPage(JSONObject jsonObject) {
        JSONObject page = jsonObject.getJSONObject("page");
        if (page == null) {
            return null;
        }
        Integer current = page.getInteger("current");
        Integer size = page.getInteger("size");
        Page<T> page1 = new Page(current, size);
        return page1;
    }
}
